package com.wang.project.aop;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.wang.project.annotation.AuthCheck;
import com.wang.project.common.ErrorCode;
import com.wang.project.exception.BusinessException;
import com.wang.project.model.entity.User;
import com.wang.project.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 权限校验 AOP
 * <p>
 * 有了 Aspect 注解，那这个就会被注册到spring容器中（IOC）。
 *
 * @author yupi
 */
@Aspect
@Component
public class AuthInterceptor {

    @Resource
    private UserService userService;

    /**
     * 执行拦截
     *
     * @param joinPoint
     * @param authCheck
     * @return
     * @Around("@annotation(authCheck)") 对有这个注解的方法进行拦截
     */
    @Around("@annotation(authCheck)")
    public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
        //将给方法上的给的角色权限适用范围放到集合中。
        List<String> anyRole = Arrays.stream(authCheck.anyRole()).filter(StringUtils::isNotBlank).collect(Collectors.toList());
        //获取方法上必须要有的权限，否则这个方法不执行（抛异常）。
        String mustRole = authCheck.mustRole();
        //RequestContextHolder 全局Request上下文
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        //获取当前上下文的 HttpServletRequest
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        // 当前登录用户（根据request）
        User user = userService.getLoginUser(request);
        // 拥有任意权限即通过  只有当anyRole不为空才判断
        if (CollectionUtils.isNotEmpty(anyRole)) {
            String userRole = user.getUserRole();
            //如果当权角色的权限不在方法上注解中指定的角色中，就抛异常
            if (!anyRole.contains(userRole)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
        }
        // 必须有所有权限才通过
        if (StringUtils.isNotBlank(mustRole)) {
            String userRole = user.getUserRole();
            //看当前用户的角色权限，是否是must必须要的权限，如果不是，则抛异常。
            if (!mustRole.equals(userRole)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
        }

        //如果anyRole为空，也就是没有在方法上写AuthCheck注解，则默认通过
        // 通过权限校验，放行
        return joinPoint.proceed();
    }
}

